package utils

import (
	"fmt"
	"math/rand"
	"time"
)

func getTimeTick64() int64 {
	return time.Now().UnixNano() / 1e6
}

func getTimeTick32() int32 {
	return int32(time.Now().Unix())
}

func getFormatTime(time time.Time) string {
	return time.Format("20060102")
}

// GenerateCode32 基础做法 日期20191025时间戳1571987125435+3位随机数
func GenerateCode32() string {
	date := getFormatTime(time.Now())
	r := rand.Intn(1000)
	code := fmt.Sprintf("%s%d%03d", date, getTimeTick32(), r)
	return code
}

// GenerateCode64 基础做法 日期20191025时间戳1571987125435+3位随机数
func GenerateCode64() string {
	date := getFormatTime(time.Now())
	r := rand.Intn(1000)
	code := fmt.Sprintf("%s%d%03d", date, getTimeTick64(), r)
	return code
}

const (
	codeLength    = 8
	characters    = "0123456789abcdefghijklmnopqrstuvwxyz"
	rounds        = 3  // 扩散轮数
	shuffleRounds = 10 // 混淆轮数
)

func GenerateInviteCode(seed string) string {
	rand.Seed(time.Now().UnixNano())

	// 扩散
	code := diffuse(seed, rounds)

	// 混淆
	code = shuffle(code, shuffleRounds)

	// 裁剪到指定长度
	code = code[:codeLength]

	return code
}

func diffuse(input string, rounds int) string {
	for i := 0; i < rounds; i++ {
		inputBytes := []byte(input)
		outputBytes := make([]byte, len(inputBytes))

		for j := 0; j < len(inputBytes); j++ {
			outputBytes[j] = characters[(int(inputBytes[j])+j)%len(characters)]
		}

		input = string(outputBytes)
	}

	return input
}

func shuffle(input string, rounds int) string {
	inputBytes := []byte(input)

	for i := 0; i < rounds; i++ {
		rand.Shuffle(len(inputBytes), func(j, k int) {
			inputBytes[j], inputBytes[k] = inputBytes[k], inputBytes[j]
		})
	}

	return string(inputBytes)
}
